package com.lu.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 陆小根
 * date: 2022/06/27
 * Description:
 */

@RestController
@RequestMapping("/redisTest")
public class RedisTestController {
  private final StringRedisTemplate redisTemplate;

  @Autowired
  public RedisTestController(StringRedisTemplate redisTemplate) {
    this.redisTemplate = redisTemplate;
  }

  @GetMapping
  public String testRedis() {
    // 设置值到redis
    ValueOperations<String, String> ops = redisTemplate.opsForValue();
    ops.set("name", "lucy");
    // 从redis获取值
    return ops.get("name");
  }

  @GetMapping("/testLock")
  public void testLock() {
    ValueOperations<String, String> ops = redisTemplate.opsForValue();

    String uuid = UUID.randomUUID().toString();

    // 1. 获取锁, setnx
    Boolean lock = ops.setIfAbsent("lock", uuid, 3, TimeUnit.SECONDS);
    // 2. 获取锁成功、查询 num 的值
    if (lock) {
      String value = ops.get("num");
      // 2.1 判断 num 为空 返回return
      if (StringUtils.isEmpty(value)) {
        return;
      }
      // 2.2 有值就转成 int
      int num = Integer.parseInt(value);
      // 2.3 把 redis 的num加1
      ops.increment("num");
      // 2.4 释放锁 del
//
//      if (uuid.equals(ops.get("lock")))
//        redisTemplate.delete("lock");

      String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
      // 设置lua脚本返回的数据类型
      DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
      // 设置lua脚本返回类型为Long
      redisScript.setResultType(Long.class);
      redisScript.setScriptText(script);
      redisTemplate.execute(redisScript, Arrays.asList("lock"),uuid);
    } else {
      // 3 获取锁失败，每隔 0.1 秒再获取
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

}
